home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1995 January
/
Simtel - 10000 MSDOS Shareware Programs (Walnut Creek)(January 1995)(Disc 1).ISO
/
disc1
/
keyboard
/
swpkeyat.asm
< prev
next >
Wrap
Assembly Source File
|
1985-07-09
|
7KB
|
219 lines
TITLE SWPKEYAT -- Swap IBM-PC/AT Keys
SUBTTL History
; This program intercepts the IBM-PC/AT's keyboard hardware interrupt
; and messes around with the keyboard scan codes, specifically to swap the
; "Esc" and "~" keys. It then returns to the ROM BIOS for the remainder
; of the keyboard interrupt processing.
; Note that the only way that I can return to the ROM BIOS for the
; remainder of the keyboard processing is to jump to a nonstandard known
; location in ROM. This is an unfortunate practice. The only other
; option I can see is for SWPKEYAT to contain it's own copy of the entire
; keyboard interrupt code. However, I don't have time to do this yet.
; Because of the way that SWPKEYAT interacts with the keyboard
; hardware interrupt vector and the BIOS ROM, you must load this program
; BEFORE you load other keyboard processing programs, such as ScrollMate
; and BUF160. Perhaps with more effort I could devise a cleaner interface.
; Another problem is that some programs, such as Lugaru Epsilon,
; substitute their own keyboard scan interrupt routines while they are
; active. In order to easily patch such programs I have defined a special
; interrupt number, INT 3FH, which acts like an IN from the keyboard data
; port with the appropriate scan codes swapped. (INT 3FH is the last
; "Reserved for DOS" interrupt. DOS 3.10 doesn't use it, but that's no
; guarantee about future availability.)
; This version is set up for the IBM-PC/AT ROM BIOS as documented in the
; March 1984 edition of the Technical Reference for the IBM Personal Computer
; AT, keyboard BIOS module dated 01/04/84. Warning! Ignore the IBM PC/AT
; Technical Reference section "Key Scan Codes", starting on p. 4-10. It's
; completely bogus. Also, ignore the "break code prefix". Instead, relay on
; the BIOS ROM listing (p. 5-28, p. 5-115 and on) in earlier editions of
; the Technical Reference (like the Aug 1981 edition). The only new key on
; the AT, Sys Req, has scan code 84 (dec).
; swpkeyat.asm 10 Jul 85 Craig Milo Rogers at USC/ISI
; Improved some of the comments.
; swpkeyat.asm 27 Jun 85 Craig Milo Rogers at USC/ISI
; Created this program to swap the ESC key on the IBM-PC/AT with the
; tilde/grave key.
PAGE
SUBTTL Declarations
KB_DATA EQU 060H ; Keyboard data port.
BREAK_BIT EQU 080H ; Break-contact scan modifier.
ESC_SCAN EQU 001H ; Scan code for the ESC key.
TILDE_SCAN EQU 029H ; Scan code for tilde/grave key.
STATUS_PORT EQU 064H ; Keyboard status port.
INPT_BUF_FULL EQU 002H ; Input-buffer-full bit.
DIS_KBD EQU 0ADH ; Disable-keyboard command.
KB_INUM EQU 009H ; Keyboard hardware interrupt number.
SCAN_INUM EQU 03FH ; Keyboard scan request interrupt
; number.
; The following two segments are used to interface this code to the
; ROM BIOS.
BIOSDATA SEGMENT AT 40H ; BIOS data area in RAM.
BIOSDATA ENDS
BIOSROM SEGMENT AT 0F000H ; Known BIOS locations in ROM.
ORG 03054H+0ABH-08CH ; Place to reenter the keyboard
KB_INT_1A LABEL FAR ; hardware interrupt.
BIOSROM ENDS ; End of BIOS ROM segment.
CODESEG SEGMENT ; The code segment for this module.
ASSUME CS:CODESEG ; Always in CS.
; Configure for a .COM file: start
; with the Program Segment Prefix.
ORG 02CH ; The PSP environment pointer.
ENV_SEG LABEL WORD
ORG 100H ; Start of .COM execution.
BEGIN: JMP INIT ; Goto to code which initializes
; everything.
PAGE
SUBTTL KB_INT -- Keyboard Interrupt
; Control passes here when a message is ready from the keyboard.
KB_INT PROC FAR
STI ; Enable interrupts.
PUSH BP ; Save the registers just like
PUSH AX ; the ROM.
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
CLD ; Forward direction.
MOV AX,BIOSDATA ; Establish pointer to BIOS data.
MOV DS,AX
; Disable the keyboard:
SUB CX,CX ; Clear counter for max cycles.
CLI ;;; Disable interrupts.
LOOP1: IN AL,STATUS_PORT ;;; Read the keyboard status port.
TEST AL,INPT_BUF_FULL ;;; Is the command buffer still full?
LOOPNZ LOOP1 ;;; (yes, continue spinning)
MOV AL,DIS_KBD ;;; Get command to disable keyboard.
OUT STATUS_PORT,AL ;;; Send it out.
STI ;;; Reenable interrupts.
NOP ; Window for interrupts.
; Wait for the keyboard to pick up
; the command:
SUB CX,CX ; Clear counter for max cycles.
CLI ;;; Disable interrupts.
LOOP2: IN AL,STATUS_PORT ;;; Read the keyboard status port.
TEST AL,INPT_BUF_FULL ;;; Is the command buffer still full?
LOOPNZ LOOP2 ;;; (yes, continue spinning)
STI ;;; Reenable interrupts.
INT SCAN_INUM ; Read the scan code.
JMP KB_INT_1A ; Go enter the mainline ROM code.
KB_INT ENDP
PAGE
SUBTTL SCAN_INT -- Get a Keyboard Scan Code
SCAN_INT PROC FAR ; Get a keyboard scan code.
STI ; Enable interrupts.
IN AL,KB_DATA ; Pick up the waiting scan code.
PUSH AX ; Save the full scan.
AND AL,NOT BREAK_BIT ; Eliminate the break bit.
CMP AL,ESC_SCAN ; Is this an ESC?
JE SAW_ESC ; (yes)
CMP AL,TILDE_SCAN ; Is this a tilde?
JE SAW_TILDE ; (yes)
POP AX ; Restore the full code.
IRET ; Return to caller.
SAW_ESC:POP AX ; Restore the full scan code.
AND AL,BREAK_BIT ; Retain the break bit.
OR AL,TILDE_SCAN ; Remap into a tilde.
IRET ; Return to the caller.
SAW_TILDE:
POP AX ; Restore the full scan code.
AND AL,BREAK_BIT ; Retain the break bit.
OR AL,ESC_SCAN ; Remap into an escape.
IRET ; Return to the caller.
SCAN_INT ENDP
PAGE
SUBTTL INIT -- Initialize and Exit-staying-resident
INIT PROC NEAR ; Initialize and exit.
ASSUME DS:CODESEG ; Entered with CS and DS pointing to
; the Program Segment Prefix, which
; the first 100H locations of CODESEG.
; Grab the keyboard hardware int.:
MOV DX,OFFSET KB_INT ; Address of int. routine in DS:DX.
MOV AL,KB_INUM ; Keyboard hardware interrupt.
MOV AH,025H ; Set interrupt vector function.
INT 21H ; Call DOS to take over the interrupt.
; Grab our special keyboard scan int.:
MOV DX,OFFSET SCAN_INT ; Address of int. routine in DS:DX.
MOV AL,SCAN_INUM ; Keyboard scan input request.
MOV AH,025H ; Set interrupt vector function.
INT 21H ; Call DOS to take over the interrupt.
; Return our environment block to
; free storage:
MOV AX,ENV_SEG ; Get our environment block's segment.
MOV ES,AX
MOV AH,049H ; Free allocated memory.
INT 21H ; Call DOS.
; Ignore possible error return.
; Terminate and stay resident. Start
; By calculating how much memory to
; leave allocated to this program:
MOV DX,OFFSET INIT ; Don't need to retain init routine.
ADD DX,0FH ; Round up to a paragraph.
MOV CL,4
SHR DX,CL
MOV AL,0 ; Successful return.
MOV AH,031H ; Terminate process & remain resident.
INT 21H ; Call DOS.
XOR AH,AH ; Emergency exit in case of DOS 1.
INT 21H
INIT ENDP
CODESEG ENDS
END BEGIN